<?php

namespace App\Services;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Model\Meeting;
use App\Services\Dao\MeetingDao;
use App\Services\Formatter\MeetingFormatter;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Collection;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Codec\Json;

class MeetingService
{
    /**
     * @Inject
     * @var MeetingDao
     */
    protected $meetingDao;

    /**
     * @Inject
     * @var MeetingFormatter
     */
    protected $formatter;

    /**
     * 保存活动数据
     * @param int $id
     * @param int $userId
     * @param array $data
     * @return bool
     */
    public function save(int $id, int $userId, array $data): bool
    {
        if ($id > 0) {
            $model = $this->meetingDao->findMeetingById($id);
            if ($model->user_id !== $userId) {
                throw new BusinessException(ErrorCode::AUTH_INVALID, ErrorCode::getMessage(ErrorCode::AUTH_INVALID));
            }
            if ($model->status === 1) {
                throw new BusinessException(ErrorCode::MEETING_IS_BEGIN, ErrorCode::getMessage(ErrorCode::MEETING_IS_BEGIN));
            }
        } else {
            $model = new Meeting();
            $model->user_id = $userId;
        }
        $model->title = $data['title'];
        $model->content = $data['content'];
        $model->user_limit = $data['userLimit'];
        $model->sign_rules = Json::encode($data['signRules']);
        $model->sign_fields = isset($data['signFields']) ? Json::encode($data['signFields']) : '';
        $model->sign_type = $data['signType'];
        $model->allow_later_sign = $data['allowLaterSign'] ?? 0;
        $model->is_publish = $data['isPublish'] ?? 0;
        $model->status = $data['status'] ?? 0;
        $model->sign_in_start = $data['signInStart'] ?? null;
        $model->sign_in_end = $data['signInEnd'] ?? null;
        $model->sign_out_start = $data['signOutStart'] ?? null;
        $model->sign_out_end = $data['signOutEnd'] ?? null;
        $model->supplementary_start = $data['supplementaryStart'] ?? null;
        $model->supplementary_end = $data['supplementaryEnd'] ?? null;

        return $model->save();
    }

    /**
     * @param int $id
     * @param int $userId
     * @return array
     */
    public function findInfo(int $id, int $userId = 0): array
    {
        $model = $this->meetingDao->findMeetingById($id);
        if (empty($model)) {
            throw new BusinessException(ErrorCode::MEETING_NOT_EXIST, ErrorCode::getMessage(ErrorCode::MEETING_NOT_EXIST));
        }
        if ($userId > 0 && $model->user_id !== $userId) {
            throw new BusinessException(ErrorCode::AUTH_INVALID, ErrorCode::getMessage(ErrorCode::AUTH_INVALID));
        }
        return $this->formatter->stdoutFormatter($model);
    }

    /**
     * note:查找活动-不抛异常处理
     * @param int $id
     * created by: lhw at 14/1/2022 9:16 下午
     * @return array
     */
    public function findInfoById(int $id): array
    {
        $model = $this->meetingDao->socketFindMeetingById($id);
        if (empty($model)) {
            return [];
        }
        return $this->formatter->stdoutFormatter($model);
    }

    /**
     * note:所有活动分页数据(我管理的)
     * @param int $userId
     * @param int $limit
     * created by: lhw at 10/1/2022 9:11 下午
     * @return array
     */
    public function findAllMeetingByUserId(int $userId, int $limit = 10): array
    {
        $result = $this->meetingDao->findAllMeetingsByUserId($userId, $limit);
        $items = $this->formatter->formatList($result->items());
        return [$result->total(), $items];
    }

    /**
     * 删除(已结束的才能删除)
     * @param int $id
     * @param int $userId
     * @return bool|int|mixed|null
     * @throws \Exception
     */
    public function deleteMeeting(int $id, int $userId)
    {
        $model = $this->meetingDao->findMeetingById($id);
        if (empty($model)) {
            throw new BusinessException(ErrorCode::MEETING_NOT_EXIST, ErrorCode::getMessage(ErrorCode::MEETING_NOT_EXIST));
        }
        if ($model->user_id !== $userId) {
            throw new BusinessException(ErrorCode::AUTH_INVALID, ErrorCode::getMessage(ErrorCode::AUTH_INVALID));
        }
        if ($model->status !== 2) {
            throw new BusinessException(ErrorCode::MEETING_NOT_END, ErrorCode::getMessage(ErrorCode::MEETING_NOT_END));
        }
        return $model->delete();
    }

    /**
     * note:取消活动(未开始或进行中的)
     * @param int $id
     * @param int $userId
     * created by: lhw at 10/1/2022 9:51 下午
     * @return bool
     */
    public function cancelMeeting(int $id, int $userId): bool
    {
        $model = $this->meetingDao->findMeetingById($id);
        if (empty($model)) {
            throw new BusinessException(ErrorCode::MEETING_NOT_EXIST, ErrorCode::getMessage(ErrorCode::MEETING_NOT_EXIST));
        }
        if ($model->user_id !== $userId) {
            throw new BusinessException(ErrorCode::AUTH_INVALID, ErrorCode::getMessage(ErrorCode::AUTH_INVALID));
        }
        if (!in_array($model->status, [0, 1])) {
            throw new BusinessException(ErrorCode::MEETING_HAD_END, ErrorCode::getMessage(ErrorCode::MEETING_HAD_END));
        }
        $model->is_publish = 0;
        return $model->save();
    }

    /**
     * note: 所有未结束的活动
     * @return Builder[]|Collection
     */
    public function allNoFinishMeetings()
    {
        return Meeting::query()->where('is_publish', '=', 1)
               ->whereIn('status', [0, 1])->get();
    }
}
